#include <time.h>
#include "utils.hpp"
#include "agent.hpp"
#include "counter.hpp"

// 全局总代价
double Global_Fit(Agent* agent, uint32_t tsk) {
    double cost = 0;
    for (int i = 0; i < N; i++)
        cost += agent[i].ccost;
    cost += UNCOVER_WEIGHT * CountSetBits(tsk ^ ((1<<M) - 1));
    return cost;
}

int main() {
    srand(time(0));
    Mat matC = read_csv("../data/matC.csv");  // 卫星执行任务载荷能量消耗矩阵 0表示无法执行该任务
    Mat matD = read_csv("../data/matD.csv");  // 卫星执行任务侧摆角度 0表示无法执行该任务
    Mat matFT = read_csv("../data/matFT.csv");  // 需要执行的任务数量，和每个任务的编号
    Mat matNeighbor = read_csv("../data/matNeighbor.csv");  // 每个卫星的邻居数量，和每个邻居的编号
    Agent stlt[N];  // N个卫星(satellite)
    Mat matdata;  // 临时数据
    for (int i = 0; i < N; i++) {  // 初始化
        stlt[i].id = i;
        stlt[i].matC = matC.atr(i).T();
        stlt[i].matD = matD.atr(i).T();
        for (int j = 0; j < matNeighbor.at(i, 0); j++)  // 每行的第一列(i,0)为邻居数量
            stlt[i].neighbor |= (1 << uint32_t(N - matNeighbor.at(i, j+1)));  // 将邻居存入
        for (int j = 0; j < matFT.at(i, 0); j++)  // 每行的第一列(i,0)为可行任务数量
            stlt[i].feasibleTask |= 1 << uint32_t(M - (matFT.at(i, j+1)));  // 将任务存入
        matdata = read_csv("../data/matJointF" + to_string(i+1) + ".csv");  // 每个卫星的策略集
        for (int j = 0; j < matdata.row(); j++)  // 每一行为一个策略
            if (matdata.at(j, matdata.col()-2) == 1)  // 倒数第2列为策略是否可用的标志
                stlt[i].feasibleStrategy.push_back(j);  // 将可用的策略编号存入
    }
    matC.Clear(); matD.Clear(); matFT.Clear(); matNeighbor.Clear();

    uint32_t cnt=1;  // 5个个体的策略总数等于每个个体的有效策略的乘积
    uint32_t task;  // 覆盖任务标志位
    uint32_t cims;  // 给定初始策略编号下的执行策略
    double value, minvalue = 1e16;  // 值，最小值
    vector<uint32_t> ans(N);  // 每个个体的有效策略数量，和最优策略
    for (uint32_t i = 0; i < N; i++)
        ans[i] = stlt[i].feasibleStrategy.size();
    Counter c(ans);  // 策略计数器
    for (uint32_t i = 0; i < N; i++)
        cnt *= stlt[i].feasibleStrategy.size();
    for (uint32_t i = 0; i < cnt; i++) {  // 遍历每个策略求最优策略
        ans = c.get_value();
        task = 0;
        for (int j = 0; j < N; j++) {
            cims = stlt[j].SID_to_ImplementStrategy(stlt[j].feasibleStrategy[ans[j]]);
            stlt[j].ccost = stlt[j].Strategy_Cost(cims);
            task |= cims;
        }
        value = Global_Fit(stlt, task);
        if (value < minvalue) {
            minvalue = value;
            for (int j = 0; j < N; j++)
                stlt[j].bestsid = stlt[j].feasibleStrategy[ans[j]];
        }
        c.increment();
    }
    cout << minvalue << endl;
    for (int i = 0; i < N; i++)
        cout << stlt[i].bestsid << endl;
    return 0;
}
